package org.esgl3d;

import java.util.ArrayList;
import java.util.List;

import org.esgl3d.core.AndroidResourceResolver;
import org.esgl3d.loader.ObjLoader;
import org.esgl3d.primitives.Pyramid;
import org.esgl3d.rendering.RenderActivity;
import org.esgl3d.rendering.Renderer;
import org.esgl3d.scene.MeshNode;
import org.esgl3d.scene.Scene;
import org.esgl3d.ui.BitmapFont;
import org.esgl3d.ui.Label;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory.Options;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log;
import android.view.MotionEvent;

public class ExAsteroidChaseActivity extends RenderActivity implements SensorEventListener {
	private static final int MAX_ASTEROIDS = 15;
	private MeshNode parentNode;
	private Label myLabel;
	private Renderer cur;
	private int oldFps;
	private ArrayList<MeshNode> asteroids = new ArrayList<MeshNode>();
	private Mesh asteroidMesh;
	private Scene myScene;
	private ArrayList<MeshNode> kill = new ArrayList<MeshNode>();
	private Mesh pyramid;
	private float deltaX = 0;
	private float deltaY = 0;
	private float centerX = 0;
	private float centerY = 30;
	private boolean centered = false;
	private Vibrator vibrator = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);		
		
		
		vibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
	}
	
	@Override
	protected void onStart() {
		super.onStart();
		
		SensorManager sm = (SensorManager)getSystemService(SENSOR_SERVICE);
		
		List<Sensor> sensorList = sm.getSensorList(Sensor.TYPE_ORIENTATION);
		sm.registerListener(this, sensorList.get(0) , SensorManager.SENSOR_DELAY_NORMAL);
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		
		SensorManager sm = (SensorManager)getSystemService(SENSOR_SERVICE);
		sm.unregisterListener(this);
	}
	
	@Override
	public void setupScenegraph() {
		cur = getRenderer();
		 
		myScene = new Scene();
		
		// add our first pyramid
		parentNode = new MeshNode();
		pyramid = Pyramid.createColoredPyramid(cur).getMesh();
		parentNode.setGeometry(pyramid);
		parentNode.translate(0, 0, -10);
		parentNode.rotate(180, 0, 1, 0);
		//parentNode.rotate(90, 1, 0, 0);
		
		// create a second pyramid and attach it to the base with
		// a offset to the right (x)
		
		
		AndroidResourceResolver resolver = new AndroidResourceResolver(getAssets());
	
		ObjLoader loader = new ObjLoader(resolver,"comet.obj");
		asteroidMesh = loader.createMesh(cur, null);
		
		loader = new ObjLoader(resolver, "starship.obj");
		Mesh starshipMesh = loader.createMesh(cur, null);
		
		parentNode.setGeometry(starshipMesh);
		
				
		// add the first node to our scene (obviously the child pyramid is
		// attached too)
		myScene.addChild(parentNode);
		
		// set our scene as the one to render
		cur.setScene(myScene);
		
		Options opt = new  Options();
		opt.inPreferredConfig = Config.RGB_565;
		
		Bitmap font = BitmapFactory.decodeStream(resolver.getResourceStream("font.png"));
		
		BitmapFont bmpFont = new BitmapFont(cur.getTextureManager().addImage(font, true));
		myLabel = new Label(cur);
		myLabel.setBitmapFont(bmpFont);
	}
	
	@Override
	public void updateScenegraph() {
	
		// rotate the parent node
		//parentNode.rotate(0.50f, 0, 1, 0);
		
		cur.setOrthographicProjection();
		if (cur.getFpsCounter().getLastFps() != oldFps) {
			
			oldFps = cur.getFpsCounter().getLastFps();
			myLabel.setText(cur.getFpsCounter().toString() + " " + String.valueOf(asteroids.size()));
		}
		
		myLabel.setColor(Color.WHITE);
		myLabel.render(cur.getGl());
		
		if ( (asteroids.size() < MAX_ASTEROIDS) && (Math.random() <= 0.05) ) {
			MeshNode childNode = new MeshNode();
			childNode.setGeometry(asteroidMesh);
			childNode.translate((float)Math.random()*30-15, (float)Math.random()*30-15, -600);
			myScene.addChild(childNode);
			asteroids.add(childNode);
		}
		
		kill.clear();
		for (MeshNode curAsteroid : asteroids) {
			curAsteroid.translate(0,0,125f * cur.getFpsCounter().getLastDelta() / 1000);
			org.esgl3d.math.Matrix local = curAsteroid.getLocalTransformation();
			
			if ( (local.v[14] >= -15) && (local.v[14] <= -5) ) {
				float dx = local.v[12] - parentNode.getLocalTransformation().v[12];
				float dy = local.v[13] - parentNode.getLocalTransformation().v[13];
				//float dz = local.v[14] - parentNode.getLocalTransformation().v[14];
				float distance = (float)Math.sqrt((dx*dx)+(dy*dy));
				if (distance <= 5)
					vibrator.vibrate(100);
			}
			
			if (local.v[14] > 2)
				kill.add(curAsteroid);
		}
		
		
		for (MeshNode cur : kill) {
			myScene.removeChild(cur);
			asteroids.remove(cur);
		}
		
		if (centered) {
			final float max = 25;
			float dX = (deltaX-centerX);
			float dY = (deltaY-centerY);
			if (dX < -max)
				dX = -max;
			if (dX > max)
				dX = max;
			if (dY < -max)
				dY = -max;
			if (dY > max)
				dY = max;
			parentNode.translate(0.5f*dX*cur.getFpsCounter().getLastDelta()/1000, 0 ,0);
			parentNode.translate(0, 0.5f*dY*cur.getFpsCounter().getLastDelta()/1000,0);
		}
	
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		centerX = deltaX;
		centerY = deltaY;
		centered = true;
		return true;
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		//Log.d("sensor1", String.valueOf(event.values[1]));
		//Log.d("sensor2", String.valueOf(event.values[2]));
		
		deltaX = event.values[2];
		deltaY = event.values[1];
		
		
	}
}
